/*
 * Created by BAC IT Deustche Bank
 * User: Sergio Vasquez
 * Date: 5/12/2009
 * Time: 3:21 PM
 * 
 * Description:
 * 
 */
using System;
using System.Collections.Generic;
using System.Text;
using IScheduler.Core.Properties;

namespace IScheduler.Core.Schedule.Task
{
	public enum TaskStatus:int 
	{
		Starting=1,
		Started,
		Stopped,
		Stopping,
		Rerun,
		Running,
		Completed,
		Error
	};
	
	public delegate void DelegateChangedEventStatusHandler(object sender, EventArgs e);
	
	/// <summary>
	/// Description of IScheduleTask.
	/// </summary>
	public abstract class IScheduleTask : IDisposable
	{
        #region Properties

        public int Id   { get; set; }
		public string Name { get; set; }
		public int Priority { get; set; }

		private TaskStatus status;

		private DateTime duration;
		
		private TimeSpan Duration { 
			get { return duration.Subtract(DateTime.Now); }
		}
		
		public TaskStatus Status
		{ get{ return status;} 
		  set{ status = value; StatusChanged(this, EventArgs.Empty); }
		}

		public bool IsConcurrent { get; set; }
        public bool IsFaultTolerant { get; set; }
        public bool IsRunning { get; private set; }
		
		public ICollection<IScheduleFile> Files {get; set; }
		
		public event DelegateChangedEventStatusHandler StatusChanged;
        
        #endregion
		
        #region Public Instance 
        
		/// <summary>
		/// Constructor
		/// </summary>
		public IScheduleTask()
		{
			this.StatusChanged += new DelegateChangedEventStatusHandler(IScheduleTask_OnStatusChanged);
		}
		
		/// <summary>
		/// Get Task formatted Info
		/// </summary>
		/// <returns></returns>
		public virtual string GetInfo()
		{
			StringBuilder sb = new StringBuilder();
			sb.Append ("[Task:");
			sb.Append (this.ToString());
			sb.Append (",Id:");
			sb.Append (this.Id.ToString());
			sb.Append (",Name:");
			sb.Append (this.Name.ToString());
			sb.Append (",Priority:");
			sb.Append (this.Priority.ToString());
			sb.Append (",Status:");
			sb.Append (this.Status.ToString());
			sb.Append ("]");
			return sb.ToString();			
		}
		
		/// <summary>
		/// Execute Task
		/// </summary>
		public void Execute()
		{
			this.duration = DateTime.Now;
			this.Status = TaskStatus.Running;
			
			try
			{
				this.SpecificExecute();
				this.Status = TaskStatus.Completed;
			}
			catch 
			{
				//TODO: To be implemented
			}
			finally
			{
				
			}
		}		
		
		/// <summary>
		/// Stop Task
		/// </summary>
		public void Stop()
		{
			this.Status = TaskStatus.Stopping;
			try
			{
				this.SpecificStop();
				this.Status = TaskStatus.Stopped;
			}
			catch
			{
				//TODO: To be implemented
			}
		}
		
		/// <summary>
		/// Stop Task
		/// </summary>
		public void Start()
		{
			//First time we set the id_task
			log4net.GlobalContext.Properties["id_task"] = Id;
			this.Status = TaskStatus.Starting;
			
			try
			{
				this.SpecificStart();
				this.Status = TaskStatus.Started;
			}
			catch
			{
				//TODO: To be implemented
			}			
		}
				

		#endregion
 
		#region Private Instance 
		
		/// <summary>
		/// This method is fired when the Task change the status.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void IScheduleTask_OnStatusChanged (object sender, EventArgs e)
		{
			LoggingService.InfoFormatted(Resources.IScheduleTaskStatusChanged, this.Name, this.Status.ToString());
		}
		
		#endregion

        #region IDisposable Members

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        #endregion		
		
		#region Protected Instance 

		/// <summary>
		/// Specific Stop to be custom implemented by Task
		/// </summary>
		protected virtual void SpecificStop()
		{
			//custom
		}
		
		/// <summary>
		/// Specific Start to be custom implemented by Task
		/// </summary>
		protected virtual void SpecificStart()
		{
			//custom
		}
		
		/// <summary>
		/// Specific Execute Task
		/// </summary>
		protected abstract void SpecificExecute();
		
		#endregion
		
    }
}
